/**************************************************************************//**
 *
 *  \copyright  This software is the property of  Technologies. Any
 *              information contained in this doc should not be reproduced,
 *              or used, or disclosed without the written authorization from
 *               Technologies.
 *
 *  \brief      This is the source file of the adapter module based on uds
 *              platform.
 *
 *  \file       bl_adpt_uds_platform.c
 *  \ingroup    communication_adapter_module
 *  \author
 *
 *  \version    5.1.0
 *  \date       27/03/2018
 *
 *  \par        Changelist
 *      Version  | Date       | Authors          | CR# | Descriptions
 *      -------- | ---------- | ---------------- | --- | ------------
 *      01.00.00 | 25/03/2018 | xucong      | N/A | Boot010001

 *
 *****************************************************************************/
#include "bl_common.h"
#include "bl_rte.h"
#include "bl_data.h"
#include "bl_can_tp.h"
#include "bl_can_if.h"
#include "bl_dcm.h"
#include "bl_dcm_cfg.h"
#include "bl_adapter.h"
#include "bl_security.h"
#include "bl_logical_block.h"
#include "bl_memory.h"
#include "bl_memory_cfg.h"
#include "bl_data_cfg.h"

#include "bl_adpt_uds_platform.h"
#include "bl_adpt_uds_platform_cfg.h"
#include "bl_booting_cfg.h"
#include "calibration.h"

#include "common_types.h"
#include "error.h"
#include "bl_system_cfg.h"
#include "crc.h"

#include "Ls_Nm.h"
#include "eeprom_cfg.h"
#include "eeprom.h"
   
/*定义为F301，BOOT版本号*/
__root const uint8_t    u8BootID[16]@0x00007FD0 = {'V', '1', '.', '0', '0'};

//__root const uint8_t    u8EcuSerialNumber[16]@0x00007FB0= {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20};



   
//__root const uint8_t u8BootloaderSoftwareVersionNumber[9]__attribute__((section(".BOOTLOADER_SOFTWARE_VERSION_NUMBER"))) = {0x4d,0x54,0x00,0x11,0xac,0x1e,0x00,0x00,0x00};
/*   定义使用的配置及型号，有且只有一个 */
#define    SWS_BOOT_SW_HIGH    0x30
#define    SWS_BOOT_SW_MID     0x30
#define    SWS_BOOT_SW_LOW     0X36
__root const uint8_t     u8BootSw[16]@0x00007FC0= {'B','O','O','T','-','S','W',SWS_BOOT_SW_HIGH,SWS_BOOT_SW_MID,SWS_BOOT_SW_LOW,0xff,0xff,0xff,0xff,0xff,0xff}; //M3 boot版本号不要求，预留
/* 
SW01:   FIRST VER
SW02:  SOFTCODE ,HARDWARE,PARTNUM  IN BOOT,ENABLE SVD
SW03:  ENABLE WDT
*/





#define   SWS_CONFIG_SA5_HIGH

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  SF  PROJECT START */
#ifdef   SWS_CONFIG_SF_HIGH              /////////ZF01SFH01SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x0a,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x00,0x02,0x00,0x11,0xc4,0x1e,0x00,0x00,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'S','F','H','-','3','4','0','2','0','1','0','B',' ',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_SF_MID               /////////ZF01SFH03SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x0a,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x00,0x02,0x00,0x11,0xc4,0x1e,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'S','F','H','-','3','4','0','2','0','1','0','A',' ',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_SF_LOW               /////////ZF01SFH02SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x0a,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x00,0x02,0x00,0x11,0xc4,0x1e,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'S','F','H','-','3','4','0','2','0','1','0',' ',' ',0xff,0xff,0xff};
#endif
/*SF  PROJECT END */
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  SQ  PROJECT START */
#ifdef   SWS_CONFIG_SQ_HIGH               /////////ZF01SQH01SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x0a,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x00,0x02,0x00,0x11,0xBB,0x1e,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'S','Q','H','-','3','4','0','2','0','1','0','A',' ',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_SQ_MID               /////////ZF01SQH02SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x0a,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x00,0x02,0x00,0x11,0xBB,0x1e,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'S','Q','H','-','3','4','0','2','0','1','0',' ',' ',0xff,0xff,0xff};
#endif
/*SQ  PROJECT END */
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* UFE PROJECT  START */
#ifdef   SWS_CONFIG_UFE_HIGH           /////////JS01UFE03SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x12,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xC5,0x1e,0x00,0x00,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'U',  'F', 'E', 'A', '-', '3', '4', '0', '2', '0', '1', '0', 'B',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_UFE_MID            /////////JS01UFE02SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x12,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xC5,0x1e,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'U','F','E','A','-','3','4','0','2','0','1','0','A',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_UFE_LOW            /////////JS01UFE01SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x12,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xC5,0x1e,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'U','F','E','A','-','3','4','0','2','0','1','0',' ',0xff,0xff,0xff};
#endif
/* UFE PROJECT END */
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* HA3H PROJECT  START */
#ifdef   SWS_CONFIG_HA3H_HIGH          /////////JS01HA3H03SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x12,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xac,0x1e,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'H','A','3','H','-','3','4','0','2','0','1','0','B',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_HA3H_MID           /////////JS01HA3H02SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x12,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xac,0x1e,0x00,0x01,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'H','A','3','H','-','3','4','0','2','0','1','0','A',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_HA3H_LOW
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x12,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xac,0x1e,0x00,0x01,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'H','A','3','H','-','3','4','0','2','0','1','0',' ',0xff,0xff,0xff};
#endif
/* HA3H PROJECT END */
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* EKEA PROJECT START*/
#ifdef   SWS_CONFIG_EKEA_MID        /////////
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x06,0x0a,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4D,0x54,0x00,0x11,0x91,0x1e,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'E','K','E','A','-','3','4','0','2','0','1','0','A',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_EKEA_LOW       /////////JS01EKEA01SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x05,0x0a,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t u8SoftCodeNumber[16]@0x00007FE0= {0x4D,0x54,0x00,0x11,0x91,0x1e,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'E','K','E','A','-','3','4','0','2','0','1','0',' ',0xff,0xff,0xff};
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  HTH PROJECT START */
#ifdef   SWS_CONFIG_HTH_HIGH         /////JS01HTH02SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x09,0x13,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xDE,0x1E,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'H','T','H','-','3','4','0','2','0','1','0','A',' ',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_HTH_LOW         /////JS01HTH01SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x09,0x13,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x11,0xE0,0x1E,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8PartNumber[16]@0x00007FF0= {'H','T','H','-','3','4','0','2','0','1','0',' ',' ',0xff,0xff,0xff};
#endif
/*  HTH PROJECT END */

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  HA6H PROJECT START */
#ifdef   SWS_CONFIG_HA6H_MID               /////////JS01HA6H03SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x06,0x0A,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x12,0xA2,0x1E,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0= {'H','A','6','-','3','4','0','2','0','1','0','A',' ',0xff,0xff,0xff};
#endif
#ifdef   SWS_CONFIG_HA6H_LOW              /////////JS01HA6H01SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0= {0x01,0x17,0x06,0x0A,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8SoftCodeNumber[16]@0x00007FE0= {0x4d,0x54,0x00,0x12,0xA2,0x1E,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8PartNumber[16]@0x00007FF0= {'H','A','6','-','3','4','0','2','0','1','0',' ',' ',0xff,0xff,0xff};
#endif
/*  MC PROJECT END */
#ifdef   SWS_CONFIG_MCH_MID               /////////JS01HA6H03SW06
__root const uint8_t    u8HardVersion[16]@0x00007FD0=    {0x01,0x17,0x05,0x012,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8SoftCodeNumber[16]@0x00007FE0= {0x56,0x47,0x00,0x10,0xA9,0x1E,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t     u8PartNumber[16]@0x00007FF0=    {'M','C','H','-','3','4','0','2','0','1','0','A',' ',0xff,0xff,0xff};
#endif
/*  MC PROJECT END */
#ifdef   SWS_CONFIG_SA5_HIGH               /////////JS01SA503SW06
//__root const uint8_t    u8HardVersion[16]@0x00007FD0=    {0x01,0x17,0x05,0x012,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
__root const uint8_t    u8SoftCodeNumber[16]@0x00007FE0;
__root const uint8_t     u8PartNumber[16]@0x00007FF0=    {'3','4','0','2','1','0','0','V','0','3','X','U',0x00,0x00,0x00,0x00};
#endif

/* EKEA PROJECT END*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef UDS_DEBUG_EN
typedef struct
{
	u16 data[2];
	u16 time[8];
}usd_test_s;
usd_test_s g_usd_test = {0};
#endif


/*****************************************************************************
 *  Verify The Configurations of Macro
 *****************************************************************************/
#if (DCM_BUFFER_SIZE < ADPT_MAXNUM_OF_BLOCKLENGTH)
#error "the buffer of the Dcm module is too small."
#endif

#if (RTE_FUN_GATEWAY == BL_FUN_ON)
#error "the function of gateway is not ok."
#endif
/*****************************************************************************
 *  Internal Macro Definitions
 *****************************************************************************/
/*lint -emacro(778,ADPT_SESSION_RESPONSE0,ADPT_SESSION_RESPONSE1)*/
/*lint -emacro(778,ADPT_SESSION_RESPONSE2,ADPT_SESSION_RESPONSE3)*/
/*lint -emacro(572,ADPT_SESSION_RESPONSE0,ADPT_SESSION_RESPONSE1)*/
/*lint -emacro(572,ADPT_SESSION_RESPONSE2,ADPT_SESSION_RESPONSE3)*/
#define ADPT_P2START_TIMER          (DCM_P2STARTIMEVALUE/DCM_P2STARTIMER_DIV)
#define ADPT_SESSION_RESPONSE0      (u8)(((u16)DCM_P2TIMEVALUE >> 8) & 0xFFu)
#define ADPT_SESSION_RESPONSE1      (u8)(((u16)DCM_P2TIMEVALUE >> 0) & 0xFFu)
#define ADPT_SESSION_RESPONSE2      (u8)(((u16)ADPT_P2START_TIMER >> 8) & 0xFFu)
#define ADPT_SESSION_RESPONSE3      (u8)(((u16)ADPT_P2START_TIMER >> 0) & 0xFFu)

#define ADPT_MEMORY_LEN_FORMAT          (0x04u)
#define ADPT_MEMORY_ADDR_FORMAT         (0x04u)

#define ADPT_MEMORY_LENANDADDR_FORMAT   ((ADPT_MEMORY_LEN_FORMAT << 4) \
										   | ADPT_MEMORY_ADDR_FORMAT)

#define ADPT_ERASE_DATA_LENGTH          (0x01u \
										   + ADPT_MEMORY_LEN_FORMAT \
										   + ADPT_MEMORY_ADDR_FORMAT)
#define ADPT_CHECKSUM_LENGTH            (0x04u)

#define ADPT_DATAFORMAT_IDEN            (0x00u)
#define ADPT_LENFORMAT_IDEN             (0x20u)
#define ADPT_IDEN_LEN_FORMAT            ((ADPT_LENFORMAT_IDEN >> 4) & 0x0Fu)
#define ADPT_REQDOWNLOAD_RESPLENGTH     (0x01u + ADPT_IDEN_LEN_FORMAT)

/** \brief Indicate the 31 service is ok.*/
#define ADPT_ROUTINE_CORRECT_RESULT     (0u)  //(0) // GL =  4	//31應答，FE-5HA是 4 和 5
/** \brief Indicate the 31 service is not ok.*/
#define ADPT_ROUTINE_INCORRECT_RESULT   (1u)  //(1) // GL = 5
#define ADPT_ROUTINE_INCORRECT_SIG_RESULT   (2u)  //(1) // GL = 5
#if 0  //目前沒有用到
#define ADPT_ROUTINE_NOT_ALL_MANDATORY_BLOCKS_PRESENT_RESULT   (6)  // 31  FF 01

#define ADPT_ROUTINE_HW_INCOMPATIBILITY_RESULT   (7)  // 31  FF 01
#define ADPT_ROUTINE_SW_INCOMPATIBILITY_RESULT   (8)  // 31  FF 01
#endif

#define ADPT_UDS_SYSTEM_STATUS_MASK     (RTE_SYSFLAG_WRITE_FINGPRINT \
											| ADPT_SYSTEM_STATUS_MASK)  //1c

#define ADPT_UDS_STATUS_MASK            (ADPT_STATUS_ALLOW_TRANS_DATA \
											| ADPT_STATUS_BLOCK_FIRST_DATA \
											| ADPT_STATUS_SEGMENT_FIRST_DATA)  //78000000

#define ADPT_UDS_36_SERVICE_ID              (0x36u)
#define ADPT_UDS_31_SERVICE_ID              (0x31u)
#define ADPT_UDS_3E_SERVICE_ID              (0x3Eu)
#define ADPT_UDS_11_SERVICE_ID              (0x11u)

#define ADPT_UDS_36_SERVICE_INDEX_POS       (0x00u)
#define ADPT_UDS_36_SERVICE_DATA_POS        (0x01u)

#define ADPT_UDS_ERASE_MEMORY_FORMAT_POS    (0)  // 44開始
#define ADPT_UDS_ERASE_MEMORY_ADDRESS_POS   (1)
#define ADPT_UDS_ERASE_MEMORY_SIZE_POS      (5)

#define ADPT_UDS_34_SERVICE_IDEN_POS        (0)
#define ADPT_UDS_34_SERVICE_ADDRANDSIZE_POS (1)
#define ADPT_UDS_34_SERVICE_ADDRESS_POS     (2)
#define ADPT_UDS_34_SERVICE_SIZE_POS        (ADPT_UDS_34_SERVICE_ADDRESS_POS \
												+ ADPT_MEMORY_ADDR_FORMAT)   //6

#define ADPT_UDS_34_RESPONSE_FORMAT_POS     (0)  // 如 20是格式
#define ADPT_UDS_34_RESPONSE_SIZE_POS       (1)		// 如 0402是長度


#define ADPT_STATUS_ALLOW_TRANS_DATA        DCM_MAKE_FLAG(0x20000000UL)  //允许传输数据
#define ADPT_STATUS_BLOCK_FIRST_DATA        DCM_MAKE_FLAG(0x10000000UL)	//阻止第一个数据块的传输
#define ADPT_STATUS_SEGMENT_FIRST_DATA      DCM_MAKE_FLAG(0x08000000UL) //将第一个数据块分段传输

#define ADPT_UDS_MAX_CAN_FRAME_SIZE         (CANTP_MAX_FRAME_SIZE)    //好好查一下該宏 
#define ADPT_UDS_CAN_FRAME_INDEX_0          (0)
#define ADPT_UDS_CAN_FRAME_INDEX_1          (1)
#define ADPT_UDS_CAN_FRAME_INDEX_2          (2)
#define ADPT_UDS_CAN_FRAME_INDEX_3          (3)
#define ADPT_UDS_CAN_FRAME_INDEX_4          (4)
#define ADPT_UDS_CAN_FRAME_INDEX_5          (5)
#define ADPT_UDS_CAN_FRAME_INDEX_6          (6)
#define ADPT_UDS_CAN_FRAME_INDEX_7          (7)
#define ADPT_UDS_CAN_FRAME_INDEX_8          (8)

/*****************************************************************************
 *  Internal Type Definitions
 *****************************************************************************/
/** \brief A alias of struct _tag_AdapterData.*/
typedef struct _tag_AdapterData bl_AdapterData_t;

#if (RTE_FUN_GATEWAY == BL_FUN_ON)
/** \brief A alias of struct _tag_GatewayTransmitList.*/
typedef struct _tag_GatewayTransmitList bl_GatewayTransmitList_t;
/** \brief A alias of struct _tag_GatewayConversion.*/
typedef struct _tag_GatewayConversion bl_GatewayConversion_t;
#endif

/*****************************************************************************
 *  Internal Structure Definitions
 *****************************************************************************/
/** \brief This is data of a adapter.*/
struct _tag_AdapterData
{
	struct _tag_SecurityDelay delay;    /**< security access delay*/
	bl_u8_t blockIndex;     /**< the block index of 36 service*/
	bl_Buffer_t serviceId;  /**< the id of processing service*/
	bl_Address_t address;   /**< the address of 36 service*/
	bl_Size_t remainSize;   /**< the remain size of 36 service*/
};

#if(RTE_FUN_GATEWAY == BL_FUN_ON)
/** \brief This is a list of gateway transmission.*/
struct _tag_GatewayTransmitList
{
	bl_u16_t handle;
	bl_u16_t number;
	struct _tag_GatewayConversion *data;
};

/**
 * \brief This is info of gateway conversion, it includes services
 *        needed to be transmitted.
 */
struct _tag_GatewayConversion
{
	bl_u8_t sid;
	bl_u16_t size;
	bl_Buffer_t *data;
};

#endif
/*****************************************************************************
 *  Internal Function Declarations
 *****************************************************************************/
#if(RTE_FUN_GATEWAY == BL_FUN_ON)
/** \brief Gateway transmits messages.*/
static void _Adpt_UdsGatewayTransmit(bl_u8_t id);
#endif
/** \brief Send 0x78 negative response.*/
static void _Adpt_UdsPendingResponse(bl_u8_t id);
/** \brief Timeout callback of sending 0x78.*/
static void _Adpt_TimeOutCallBack(bl_u8_t id);
/** \brief send a response by comif.*/
static void _Adpt_SendResponse(bl_BufferSize_t size, const bl_Buffer_t *buffer);
/** \brief Set response info of session.*/
static bl_BufferSize_t _Adpt_SetSessionResp(bl_Buffer_t *buffer);
/** \brief Goto the session.*/
static void _Adpt_UdsGotoSession(bl_DownStatus_t sessionMask);
/** \brief Reset the bootloader.*/
static void _Adpt_UdsResetSystem(bl_u8_t sid, bl_u16_t flagId);
/** \brief Clear the download information.*/
static void _Adpt_UdsClearDownInfo(bl_AdapterData_t *adpt);

/*****************************************************************************
 *  Internal Variable Definitions
 *****************************************************************************/
/** \brief Private data variable.*/
STATIC bl_AdapterData_t gs_UdsPrivateData;
#if 0
struct _tag_AdapterData
{
	struct _tag_SecurityDelay delay;    /**< security access delay*/
	bl_u8_t blockIndex;     /**< the block index of 36 service*/
	bl_Buffer_t serviceId;  /**< the id of processing service*/
	bl_Address_t address;   /**< the address of 36 service*/
	bl_Size_t remainSize;   /**< the remain size of 36 service*/
};
#endif

#if ADPT_UDS_MAX_CAN_FRAME_SIZE <=8
STATIC const bl_Buffer_t gs_DefaultResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x06u,0x50u,0x01u,ADPT_SESSION_RESPONSE0,ADPT_SESSION_RESPONSE1,
	ADPT_SESSION_RESPONSE2,ADPT_SESSION_RESPONSE3,CANTP_FRAME_PADDING_VALUE
};
#else
STATIC const bl_Buffer_t gs_DefaultResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x00,0x06u,0x50u,0x01u,ADPT_SESSION_RESPONSE0,ADPT_SESSION_RESPONSE1,
	ADPT_SESSION_RESPONSE2,ADPT_SESSION_RESPONSE3
};
#endif

#if ADPT_UDS_MAX_CAN_FRAME_SIZE <=8
STATIC const bl_Buffer_t gs_ReprogrammingResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE]=
{
	0x06u,0x50u,0x02u,ADPT_SESSION_RESPONSE0,ADPT_SESSION_RESPONSE1,
	ADPT_SESSION_RESPONSE2,ADPT_SESSION_RESPONSE3,CANTP_FRAME_PADDING_VALUE
};
#else
STATIC const bl_Buffer_t gs_ReprogrammingResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE]=
{
	0x00,0x06u,0x50u,0x02u,ADPT_SESSION_RESPONSE0,ADPT_SESSION_RESPONSE1,
	ADPT_SESSION_RESPONSE2,ADPT_SESSION_RESPONSE3
};
#endif

#if ADPT_UDS_MAX_CAN_FRAME_SIZE <=8
STATIC const bl_Buffer_t gs_ResetResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x02u,0x51u,0x01u,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE
};
#else
STATIC const bl_Buffer_t gs_ResetResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x00,0x02u,0x51u,0x01u,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE
};
#endif

#if ADPT_UDS_MAX_CAN_FRAME_SIZE <=8
STATIC const bl_Buffer_t gs_ResetResponse_sub03[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x02u,0x51u,0x03u,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE
};
#else
STATIC const bl_Buffer_t gs_ResetResponse_sub03[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x00,0x02u,0x51u,0x03u,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE,
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE
};
#endif


#if (RTE_FUN_STAY_IN_BOOT == BL_FUN_ON)
#if ADPT_UDS_MAX_CAN_FRAME_SIZE <=8
STATIC const bl_Buffer_t gs_StayInBootResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x04u,0x71u,0x01u,ADPT_STAY_IN_BOOT_RESPONSE_HID,  //F5
	//18							AA
	ADPT_STAY_IN_BOOT_RESPONSE_LID,CANTP_FRAME_PADDING_VALUE,
	//AA 						AA
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE
};
#else
STATIC const bl_Buffer_t gs_StayInBootResponse[ADPT_UDS_MAX_CAN_FRAME_SIZE] =
{
	0x0,0x04u,0x71u,0x01u,ADPT_STAY_IN_BOOT_RESPONSE_HID,  //F5
	//18							AA
	ADPT_STAY_IN_BOOT_RESPONSE_LID,CANTP_FRAME_PADDING_VALUE,
	//AA 						AA
	CANTP_FRAME_PADDING_VALUE,CANTP_FRAME_PADDING_VALUE
};
#endif
#endif

#if(RTE_FUN_GATEWAY == BL_FUN_ON)
/** \details The data of gateway conversion. */
STATIC const bl_u8_t gs_UdsGatewayData[ADPT_UDS_CONVERSION_DATA_LENGTH] =  //2
{
	0x3Eu, 0x80u,
}

/** \details A list of gateway transmission. */
STATIC const bl_GatewayTransmitList_t gs_UdsGatewayList =
{
	ADPT_UDS_COMOPS_HANDLE,  //0XFFFF
	ADPT_UDS_NUMBER_OF_GATEWAY,  //1
	gs_UdsGateway,
};

/** \details The info of gateway conversion. */
STATIC const bl_GatewayConversion_t gs_UdsGateway[ADPT_UDS_NUMBER_OF_GATEWAY] =  //1
{
	{
		ADPT_UDS_3E_SERVICE_ID,   // SID= 3E
		ADPT_UDS_CONVERSION_DATA_LENGTH,  //SZIE =2
		gs_UdsGatewayData  // 內容指針 指向 gs_UdsGatewayData 3e 80
	},
};

#endif

/*****************************************************************************
 *  Global Variable Definitions
 *****************************************************************************/
/** \details The Uds platform adapter informations. */
const bl_Adapter_t g_UdsPlatformAdapter =
{
	//type=0  index=0 //Init      //Callback
	0x00u, 0x00u, &Adpt_UdsInit, &Adpt_UdsCallback,
	//PeriodCallback             //Timeout
	&Adpt_UdsPeriodicCallback, &Adpt_UdsTimeOutCallBack,
	//Sleep 目前沒有sleep
#if (RTE_FUN_SYSTEM_SLEEP == BL_FUN_ON)
	&Canif_Sleep,
#else
	BL_NULL_PTR, /*RTE_FUN_SYSTEM_SLEEP is OFF*/
#endif
};
/*****************************************************************************
 *  Function Definitions
 *****************************************************************************/
/**************************************************************************//**
 *
 *  \details Initialize the uds module. This function mainly initialize
 *           CanTp, dcm and security access delay info.
 *
 *  \return If Initialization is successful return BL_ERR_OK,
 *          otherwise return BL_ERR_NOT_OK.
 *
 *  \retval BL_ERR_OK       - Initialize successfully.
 *  \retval BL_ERR_NOT_OK   - Initialize unsuccessfully.
 *
 *  \note This function is called by the process driver module.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_Return_t Adpt_UdsInit(void)
{
	bl_Return_t ret;

	//ret = Canif_Init(); //己在Rte_PreInit初始化過了
	Cantp_Init();
	Dcm_Init();
	CanNm_Init();

	gs_UdsPrivateData.serviceId = 0;

	Adpt_InitDelayInfo(&gs_UdsPrivateData.delay);

	_Adpt_UdsGotoSession(DCM_STATUS_SESSION_DEFAULT);

	return ret;
}

/**************************************************************************//**
 *
 *  \details Periodic callback of function Rte_PeriodicSchedule. This function
 *           needs to be called periodically, and mainly handles timer of dcm,
 *           and CanTp module.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
void Adpt_UdsPeriodicCallback(void)
{
	#ifdef UDS_DEBUG_EN
	g_usd_test.time[0]++;
	if(g_usd_test.time[0]>=1000)  //果然是250us;後來改回1ms了
	{
		g_usd_test.time[0]=0;
		g_usd_test.time[1]++;
	}
	#endif
	Adpt_DelayTimeCallback(&gs_UdsPrivateData.delay);	//
	Dcm_TimerFunction();   // gs_DcmS3TimerStartFlag and  gs_DcmS3Timer
	Cantp_PeriodFunction();
	Dcm_MainFunction();
}

/**************************************************************************//**
 *
 *  \details Callback of the adapter, it should be always running. This
 *           function will be called by process driver module, and performs
 *           tx confirmation and rx indication.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
void Adpt_UdsCallback(void)
{
	#ifdef UDS_DEBUG_EN
	g_usd_test.time[2]++;
	if(g_usd_test.time[2]>=1000)
	{
		g_usd_test.time[2]=0;
		g_usd_test.time[3]++;
	}
	#endif
	Canif_TxMainFunction();
	Canif_RxMainFunction();
	Canif_BusoffMainFunction();
}

/**************************************************************************//**
 *
 *  \details Callback of default session.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *   在數組 gs_Dcm10SubIdl 中
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback1001(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;
	bl_u8_t l_buf[ADPT_UDS_MAX_CAN_FRAME_SIZE];
	bl_u8_t i;
	(void)size;

	/*programming session.*/
	ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_PROGRAMMING);
	if(BL_ERR_OK == ret)
	{
	#if 1
		if (Dcm_IsSuspendedResponse() != BL_ERR_OK)  //gs_SupPosRespFlag==0
		{
			#ifdef DEFAULT_GOTO_APP_DEFAULT_SEESION_78
			//先修改ram标志，使app能判断
			(void)Mem_Write(MEM_MEMORY_ID_RAM,DM_DATA_3_LOCAL_ADDR,DM_DATA_3_SIZE,DM_DATA_3_DDP); //
			_Adpt_UdsPendingResponse(0x10);
			#else
			for(i=0;i<8;i++)
			{
				l_buf[i] = gs_DefaultResponse[i];
			}
			for(i=8;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
			{
				l_buf[i] = CANTP_FRAME_PADDING_VALUE;
			}
			_Adpt_SendResponse((bl_BufferSize_t)sizeof(l_buf),l_buf);
			#endif
		}
		g_RteInfo.SystemReset();
	#else

		if (Dcm_IsSuspendedResponse() != BL_ERR_OK) //gs_SupPosRespFlag==0
		{
			_Adpt_SendResponse((bl_BufferSize_t)sizeof(gs_DefaultResponse),
								gs_DefaultResponse);
		}
		else
		{
			Dcm_StopS3Timer();
			 *respSize = _Adpt_SetSessionResp(buffer);
		}
		if(Lbm_IsAllValid() == BL_ERR_OK)
		{
			 Dcm_StopS3Timer();
			_Adpt_UdsGotoSession(DCM_STATUS_SESSION_DEFAULT);
			*respSize = _Adpt_SetSessionResp(buffer);
		}
		else
		{
			//(void)Dm_WriteDefaultData(BOOTM_REPROGRAM_FLAG_DID);
			g_RteInfo.SystemReset(); /// 需要注释  待调试确认是否要复位?????
		}
	#endif
	}
	else
	{

		#if 1
		//
		//#else
		/*extended session.*/
		ret = Rte_IsValidStatus(&g_DownContext,
									DCM_STATUS_SESSION_EXTENDED);
		if(BL_ERR_OK == ret)
		{
			Dcm_StopS3Timer();

			_Adpt_UdsGotoSession(DCM_STATUS_SESSION_DEFAULT);
		}

		*respSize = _Adpt_SetSessionResp(buffer);
		#endif
	}

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of programming session.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback1002(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_CONDITIONSNOTCORRECT;
	bl_Return_t ret;

	(void)size;

	ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_DEFAULT);
	if (ret != BL_ERR_OK) /*the default can not go to programming.*/
	{
		/*write flag.*/
		if(Lbm_IsAllValid() == BL_ERR_OK)
		{
			Dcm_StartS3Timer();

			Lbm_ClearBlock(&g_DownContext);  //会知道当前是 flash app 还是 flash drv, 清除为 LBM_STATUS_INVALID

			Rte_ClearAddressInfo(&g_DownContext);  // dct->segIndex

			_Adpt_UdsGotoSession(DCM_STATUS_SESSION_PROGRAMMING);

			*respSize = _Adpt_SetSessionResp(buffer);
			resCode = DCM_E_POSITIVERESPONSE;
		}
		else
		{
			(void)Dm_WriteDefaultData(BOOTM_REPROGRAM_FLAG_DID); //BOOTM_REPROGRAM_FLAG_DID
			#ifdef BOOT_STATE_PROG_DEBUG_EN
			#else
			g_RteInfo.SystemReset();
			#endif
		}
	}
	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of extended session.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback1003(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_CONDITIONSNOTCORRECT;
	bl_Return_t ret;

	(void)size;

	#if 0  //任何會話，直接進入03
	/*programming session.*/
	ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_PROGRAMMING);

	///ret = BL_ERR_NOT_OK; ///// ???
	if (ret != BL_ERR_OK) /*the programming can not go to extended.*/
	#endif
	{
		Dcm_StartS3Timer();

		_Adpt_UdsGotoSession(DCM_STATUS_SESSION_EXTENDED);

		*respSize = _Adpt_SetSessionResp(buffer);

		resCode = DCM_E_POSITIVERESPONSE;
	}

	return resCode;
}
#if 0
/**************************************************************************//**
 *
 *  \details Callback of extended session.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback1004(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_CONDITIONSNOTCORRECT;
	bl_Return_t ret;

	(void)size;

	/*programming session.*/
	ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_PROGRAMMING);

	///ret = BL_ERR_NOT_OK; ///// ???
	if (ret != BL_ERR_OK) /*the programming can not go to extended.*/
	{
		Dcm_StartS3Timer();

		_Adpt_UdsGotoSession(DCM_STATUS_SESSION_EXT_USER);

		*respSize = _Adpt_SetSessionResp(buffer);

		resCode = DCM_E_POSITIVERESPONSE;
	}

	return resCode;
}
#endif

/**************************************************************************//**
 *
 *  \details Callback of reset.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *  gs_Dcm11SubId 數組中
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback1101(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_u8_t i;
	bl_u8_t l_buf[ADPT_UDS_MAX_CAN_FRAME_SIZE];
	(void)respSize;
	(void)buffer;
	(void)size;

	if (Dcm_IsSuspendedResponse() != BL_ERR_OK)  //gs_SupPosRespFlag==0
	{
		for(i=0;i<8;i++)
		{
			l_buf[i] = gs_ResetResponse[i];
		}
		for(i=8;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
		{
			l_buf[i] = CANTP_FRAME_PADDING_VALUE;
		}
		_Adpt_SendResponse((bl_BufferSize_t)sizeof(l_buf),l_buf);
	}

	g_RteInfo.SystemReset();
	/*never return*/
	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of reset.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *  gs_Dcm11SubId 數組中
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback1103(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_u8_t i;
	bl_u8_t l_buf[ADPT_UDS_MAX_CAN_FRAME_SIZE];
	(void)respSize;
	(void)buffer;
	(void)size;

	if (Dcm_IsSuspendedResponse() != BL_ERR_OK)  //gs_SupPosRespFlag==0
	{
		for(i=0;i<8;i++)
		{
			l_buf[i] = gs_ResetResponse_sub03[i];
		}
		for(i=8;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
		{
			l_buf[i] = CANTP_FRAME_PADDING_VALUE;
		}
		_Adpt_SendResponse((bl_BufferSize_t)sizeof(l_buf),l_buf);
	}

	g_RteInfo.SystemReset();
	/*never return*/
	return resCode;
}

/*  22 F198 */
/**************************************************************************//**
 *
 *  \details Callback of reading fingerprint.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallBackReadFingerprint(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	//bl_Return_t ret = BL_ERR_OK;
	(void)size;
	/*read fingerprint.*/
	#ifdef BL_EEPROM_EN
	if(0 == IntEeprom_ReadBytes(EEPROM_START_ADDRESS, buffer, RTE_FINGERPRINT_SIZE))
	#else
	if(0)
	#endif
	{
		resCode = DCM_E_CONDITIONSNOTCORRECT;
	}
	else
	{
		*respSize = RTE_FINGERPRINT_SIZE;
	}
	return resCode;
}
/*  22 F186 */
bl_ResponseCode_t Adpt_UdsCallBackReadSession(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
        bl_Return_t ret;
        uint8_t u8session = 0;
	(void)size;
        
	ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_DEFAULT);
	if(BL_ERR_OK == ret)
        {
            u8session = 1;
        }
        
        if(u8session == 0)
        {
            ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_PROGRAMMING);
            if(BL_ERR_OK == ret)
            {
                u8session = 2;
            }        
        }
        
        if(u8session == 0)
        {
            ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_EXTENDED);
            if(BL_ERR_OK == ret)
            {
                u8session = 3;
            }        
        }


        if(u8session ==0 )
        {
            u8session = 1;
        }
	buffer[0] = u8session;


	*respSize = RTE_SESSION_SIZE;

	return resCode;
}


/*  22 F187 */
bl_ResponseCode_t Adpt_UdsCallBackReadPartNumber(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
        uint8_t * pu8Partnumber;
        uint8_t i;
        pu8Partnumber = (uint8_t *)0x0001B400;
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
        for(i=0;i<RTE_PART_NUMBER_SIZE;i++)
        {
            buffer[i] = pu8Partnumber[i];
        }
	
	*respSize = RTE_PART_NUMBER_SIZE;

	return resCode;
}

/*  2E F180 */
void blAdptWriteBootSwId(void)
{
	/* 版本升级0->1 */
	bl_u8_t cboot_sw_id[16] ={'G', 'E', 'E', 'L', 'Y', 'F', 'E','-','5','B','T','0','0','1','0','2'};
	#ifdef BL_EEPROM_EN
	(void)IntEeprom_WriteBytes(EEPROM_F180_START_ADDRESS, cboot_sw_id, RTE_BOOT_SW_ID_SIZE);
	#endif
}

/*  22 F183 改成F301 */
bl_ResponseCode_t Adpt_UdsCallBackReadBootSW_ID(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	uint8_t i;
        //bl_u8_t cboot_sw_id[10] ={'B', 'O', 'O','T', '-','S','W',SWS_BOOT_SW_HIGH,SWS_BOOT_SW_MID,SWS_BOOT_SW_LOW};
	for(i = 0; i < RTE_BOOT_SW_ID_SIZE; i ++)
	{		
          buffer[i] =u8BootID[i];
	}


	*respSize = RTE_BOOT_SW_ID_SIZE;

	return resCode;
}

/*  22 F18A */
bl_ResponseCode_t Adpt_UdsCallBackReadSupplierCode(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	uint8_t i;
	uint8_t *data_f18a;

	data_f18a = (uint8_t *)0x0001BC09;
	for(i = 0; i < RTE_SUPPLIER_CODE_SIZE; i ++)
	{
		buffer[i] = data_f18a[i];
	}


	*respSize = RTE_SUPPLIER_CODE_SIZE;

	return resCode;
}

/*  22 F193 */
bl_ResponseCode_t Adpt_UdsCallBackReadECU_HardwareVersionNumber(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	uint8_t i;
	uint8_t *data_f191;

	data_f191 = (uint8_t *)0x00007FD0;
	for(i = 0; i < RTE_ECU_HW_NUMBER_SIZE; i ++)
	{
		buffer[i] = data_f191[i];
	}


	*respSize = RTE_ECU_HW_NUMBER_SIZE;

	return resCode;
}


/*  22 F195 */
bl_ResponseCode_t Adpt_UdsCallBackReadECU_SoftwareVersionNumber(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	uint8_t i;
	uint8_t *data_f195;

       
	data_f195 = (uint8_t *)0x0001B400;
	for(i = 0; i < RTE_ECU_SW_NUMBER_SIZE; i ++)
	{
		buffer[i] = data_f195[i];
	}
       
       /* 
        buffer[0]=0x75;
        buffer[1]=0x39;
        buffer[2]=0x17;
        buffer[3]=0x0b;
        buffer[4]=0x0a;
        buffer[5]=0x00;
       */
	*respSize = RTE_ECU_SW_NUMBER_SIZE;

	return resCode;
}


/*  22 F194 */
bl_ResponseCode_t Adpt_UdsCallBackReadSoftCode(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	uint8_t i;
	uint8_t *data_f194;    
	data_f194 = (uint8_t *)0x00007fe0;
	for(i = 0; i < RTE_PARTS_SOFT_CODE_SIZE; i ++)
	{
		buffer[i] = data_f194[i];
	}


	*respSize = RTE_PARTS_SOFT_CODE_SIZE;

	return resCode;
}

/*  22 F186 */
bl_ResponseCode_t Adpt_UdsCallBackReadActiveSession(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;
	(void)size;
	buffer[0] = 0x0;
	ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_DEFAULT);
	if(BL_ERR_OK == ret)
	{
		buffer[0] = 0x01;
	}
	else
	{
		ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_PROGRAMMING);
		if(BL_ERR_OK == ret)
		{
			buffer[0] = 0x02;
		}
		else
		{
			ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SESSION_EXTENDED);
			if(BL_ERR_OK == ret)
			{
				buffer[0] = 0x03;
			}
		}
	}
	*respSize = 1;
	return resCode;
}

/*  22 F189 */
bl_ResponseCode_t Adpt_UdsCallBackReadEcuSoftVersion(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	#ifdef BL_EEPROM_EN
	if(0 == IntEeprom_ReadBytes(EEPROM_F180_START_ADDRESS+0x1AU, buffer, RTE_PGM_DATE_SIZE))
	#else
	if(0)
	#endif	
	{
		resCode = DCM_E_CONDITIONSNOTCORRECT;
	}
	else
	{
	#if 0
		if( (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0 && buffer[3] == 0 &&
			buffer[4] == 0 && buffer[5] == 0 && buffer[6] == 0 && buffer[7] == 0 &&
			buffer[8] == 0 && buffer[9] == 0 && buffer[10] == 0 && buffer[11] == 0 &&
			buffer[12] == 0 && buffer[13] == 0 && buffer[14] == 0 && buffer[15] == 0 ) || (

			buffer[0] == 0xff && buffer[1] == 0xff && buffer[2] == 0xff && buffer[3] == 0xff &&
			buffer[4] == 0xff && buffer[5] == 0xff && buffer[6] == 0xff && buffer[7] == 0xff &&
			buffer[8] == 0xff && buffer[9] == 0xff && buffer[10] == 0xff && buffer[11] == 0xff &&
			buffer[12] == 0xff && buffer[13] == 0xff && buffer[14] == 0xff && buffer[15] == 0xff )) {

			buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0x20;
			buffer[4] = buffer[5] = buffer[6] = buffer[7] = 0x20;
			buffer[8] = buffer[9] = buffer[10] = buffer[11] = 0x20;
			buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0x20;
		}
	#endif
		*respSize = 16;
	}
	return resCode;
}

/*  22 F199 */
bl_ResponseCode_t Adpt_UdsCallBackReadProgrammingDate(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	#ifdef BL_EEPROM_EN
	if(0 == IntEeprom_ReadBytes(EEPROM_START_ADDRESS+0x14, buffer, RTE_PGM_DATE_SIZE))
	#else
	if(0)
	#endif	
	{
		resCode = DCM_E_CONDITIONSNOTCORRECT;
	}
	else
	{
	#if 0
		if( (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0 && buffer[3] == 0) ||
			(buffer[0] == 0xff && buffer[1] == 0xff && buffer[2] == 0xff && buffer[3] == 0xff))
		{
			buffer[0] = 0x20;
			buffer[1] = 0x00;
			buffer[2] = 0x01;
			buffer[3] = 0x01;
		}
	#endif
		*respSize = 4;
	}
	return resCode;
}

/*  22 F18C */
bl_ResponseCode_t Adpt_UdsCallBackReadECUSerialNumber(bl_BufferSize_t size,
												  bl_Buffer_t *buffer,
												  bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	(void)size;
	uint8_t *port_number;
	uint8_t i;

	port_number = (uint8_t *)0x0001BC00;
	for(i = 0; i < RTE_ECUSERIALNUMBER_SIZE; i ++)
	{
		buffer[i] = port_number[i];
	}

	*respSize = RTE_ECUSERIALNUMBER_SIZE;

	return resCode;
}


bl_u8_t g_cur_request_level =0;  //當前請求的等級

/**************************************************************************//**
 *
 *  \details Callback of getting seed.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallbackGetSeedForLevel1(bl_BufferSize_t size,
												   bl_Buffer_t *buffer,
												   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;
#if(ADPT_FUN_DELAY_WITH_CONTINUOUS_SEED == BL_FUN_ON)
	bl_u16_t remainCount = 0;
#endif

	(void)size;

	do
	{
	#if 0  //為什麼 FE-5HA把這個給去掉了
		/*judge wheter security access is available.*/
		ret = Adpt_IsAccessible(&gs_UdsPrivateData.delay);
		if (ret != BL_ERR_OK)
		{
			resCode = DCM_E_REQUIREDTIMEDELAYNOTEXPIRED;
			break;
		}
	#endif
		ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SECURITY_UNLOCK_1);
		if(BL_ERR_OK == ret)
		{
			/*when unlock, return seed 0x00u.*/
			Bl_MemSet(buffer,0,(bl_Size_t)SECM_ACCESS_SEED_SIZE);
			break;
		}

		/*If a seed is requested, return it.*/
		ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SECURITY_WAITKEY_1);
		if(BL_ERR_OK == ret)
		{
#if(ADPT_FUN_DELAY_WITH_CONTINUOUS_SEED == BL_FUN_ON)
			/*if always request seed, decrease attemptcount.*/
			remainCount = Adpt_DecreaseAttemptCount(&gs_UdsPrivateData.delay);
			if(remainCount == 0x00u)
			{
#if(ADPT_FUN_SAVE_DELAY_FLAG == BL_FUN_ON)
				/*set security access delay flag.*/
				(void)Dm_WriteDefaultData(gs_UdsPrivateData.delay.delayFlagId);
#endif

				Rte_SetMutexDownStatus(&g_DownContext,
										DCM_STATUS_SECURITY_LOCK_1,
										DCM_SECURITYACCESS_1_MASK);

				resCode = DCM_E_EXCEEDNUMBEROFATTEMPTS;
				break;
			}
#endif
			/*return the last seed.*/
			Secm_GetSeed(buffer);

			break;
		}

		/*request a new seed.*/
		Secm_MakeNewSeed();
		/*Copy the seed to buffer*/
		Secm_GetSeed(buffer);
		/*set wait key status.*/
		Rte_SetDownStatus(&g_DownContext, DCM_STATUS_SECURITY_WAITKEY_1);

		g_cur_request_level=DCM_SA_SEED_REQ;  //level 實際值

	}while(0);/*lint !e717*/

	*respSize = SECM_ACCESS_SEED_SIZE;

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of verifying key.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
/*lint -e{818}*/
bl_ResponseCode_t Adpt_UdsCallbackVerifyKeyForLevel1(bl_BufferSize_t size,
													 bl_Buffer_t *buffer,
													 bl_BufferSize_t *respSize)
{
	bl_u16_t remainCount;
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;
         bl_u32_t calKey;
          bl_u32_t tranKey;
	do
	{
		ret = Rte_IsValidStatus(&g_DownContext,	DCM_STATUS_SECURITY_WAITKEY_1);
		if (ret != BL_ERR_OK)
		{
			resCode = DCM_E_REQUESTSEQUENCEERROR;
			break;
		}

		Secm_SetAccessLevel(0);
		/*verify key.*/
		ret = Secm_VerifyKey((bl_Size_t)size,buffer);
                 /*  
                   calKey = _Acc_UdsDemoCalculateKey();   //這是相當於本地算出來的
                   tranKey = BL_BE32_TO_MCU(buffer);  // tranKey = *key  --這是相當於 診斷上收回來的數據；BL_BE32_TO_MCU
                   if(calKey==tranKey)  ret=BL_ERR_OK;
                   else                 ret=BL_ERR_NOT_OK;
                 */
		if(ret!=BL_ERR_OK)
		{
			remainCount = Adpt_DecreaseAttemptCount(&gs_UdsPrivateData.delay);  //相當於  等 attemptCount  操作次數
			if (0x00u == remainCount)
			{
#if(ADPT_FUN_SAVE_DELAY_FLAG == BL_FUN_ON)
				/*set security access delay flag.*/
				(void)Dm_WriteDefaultData(gs_UdsPrivateData.delay.delayFlagId);
#endif
				Rte_SetMutexDownStatus(&g_DownContext,
										DCM_STATUS_SECURITY_LOCK_1,
										DCM_SECURITYACCESS_1_MASK);

				resCode = DCM_E_EXCEEDNUMBEROFATTEMPTS;
			}
			else
			{
				resCode = DCM_E_INVALIDKEY;
			}

			break;
		}

		*respSize = 0x00u;
		Rte_SetMutexDownStatus(&g_DownContext,
								DCM_STATUS_SECURITY_UNLOCK_1,
								DCM_SECURITYACCESS_1_MASK);
		}while(0);/*lint !e717*/

	return resCode;
}
/**************************************************************************//**
 *
 *  \details Callback of getting seed.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallbackGetSeedForLevel2(bl_BufferSize_t size,
												   bl_Buffer_t *buffer,
												   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;
#if(ADPT_FUN_DELAY_WITH_CONTINUOUS_SEED == BL_FUN_ON)
	bl_u16_t remainCount = 0;
#endif

	(void)size;

	do
	{
	#if 0  //為什麼 FE-5HA把這個給去掉了
		/*judge wheter security access is available.*/
		ret = Adpt_IsAccessible(&gs_UdsPrivateData.delay);
		if (ret != BL_ERR_OK)
		{
			resCode = DCM_E_REQUIREDTIMEDELAYNOTEXPIRED;
			break;
		}
	#endif
		ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SECURITY_UNLOCK_2);
		if(BL_ERR_OK == ret)
		{
			/*when unlock, return seed 0x00u.*/
			Bl_MemSet(buffer,0,(bl_Size_t)SECM_ACCESS_SEED_SIZE);
			break;
		}

		/*If a seed is requested, return it.*/
		ret = Rte_IsValidStatus(&g_DownContext, DCM_STATUS_SECURITY_WAITKEY_2);
		if(BL_ERR_OK == ret)
		{
#if(ADPT_FUN_DELAY_WITH_CONTINUOUS_SEED == BL_FUN_ON)
			/*if always request seed, decrease attemptcount.*/
			remainCount = Adpt_DecreaseAttemptCount(&gs_UdsPrivateData.delay);
			if(remainCount == 0x00u)
			{
#if(ADPT_FUN_SAVE_DELAY_FLAG == BL_FUN_ON)
				/*set security access delay flag.*/
				(void)Dm_WriteDefaultData(gs_UdsPrivateData.delay.delayFlagId);
#endif

				Rte_SetMutexDownStatus(&g_DownContext,
										DCM_STATUS_SECURITY_LOCK_2,
										DCM_SECURITYACCESS_2_MASK);

				resCode = DCM_E_EXCEEDNUMBEROFATTEMPTS;
				break;
			}
#endif
			/*return the last seed.*/
			Secm_GetSeed(buffer);

			break;
		}

		/*request a new seed.*/
		Secm_MakeNewSeed();
		/*Copy the seed to buffer*/
		Secm_GetSeed(buffer);
		/*set wait key status.*/
		Rte_SetDownStatus(&g_DownContext, DCM_STATUS_SECURITY_WAITKEY_2);

		g_cur_request_level=DCM_SA_SEED_2_REQ;  //level 實際值

	}while(0);/*lint !e717*/

	*respSize = SECM_ACCESS_SEED_SIZE;

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of verifying key.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
/*lint -e{818}*/
bl_ResponseCode_t Adpt_UdsCallbackVerifyKeyForLevel2(bl_BufferSize_t size,
													 bl_Buffer_t *buffer,
													 bl_BufferSize_t *respSize)
{
	bl_u16_t remainCount;
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;

	do
	{
		ret = Rte_IsValidStatus(&g_DownContext,
									DCM_STATUS_SECURITY_WAITKEY_2);
		if (ret != BL_ERR_OK)
		{
			resCode = DCM_E_REQUESTSEQUENCEERROR;
			break;
		}

		Secm_SetAccessLevel(1);
		/*verify key.*/
		ret = Secm_VerifyKey((bl_Size_t)size,buffer);
		if (ret != BL_ERR_OK)
		{
			remainCount = Adpt_DecreaseAttemptCount(&gs_UdsPrivateData.delay);  //相當於  等 attemptCount  操作次數
			if (0x00u == remainCount)
			{
#if(ADPT_FUN_SAVE_DELAY_FLAG == BL_FUN_ON)
				/*set security access delay flag.*/
				(void)Dm_WriteDefaultData(gs_UdsPrivateData.delay.delayFlagId);
#endif
				Rte_SetMutexDownStatus(&g_DownContext,
										DCM_STATUS_SECURITY_LOCK_2,
										DCM_SECURITYACCESS_2_MASK);

				resCode = DCM_E_EXCEEDNUMBEROFATTEMPTS;
			}
			else
			{
				resCode = DCM_E_INVALIDKEY;
			}

			break;
		}

		*respSize = 0x00u;
		Rte_SetMutexDownStatus(&g_DownContext,
								DCM_STATUS_SECURITY_UNLOCK_2,
								DCM_SECURITYACCESS_2_MASK);
	}while(0);/*lint !e717*/

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of enable or disable communication.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval DCM_E_POSITIVERESPONSE   - Positive response code.
 *  \retval DCM_E_REQUESTOUTOFRANGE - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
/*lint -e{818}*/
bl_ResponseCode_t Adpt_UdsCallback28(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;

	(void)size;
	/*if(ADPT_COMMCONTROLTYPE_DATA != buffer[0])*/
	if((ADPT_COMMCONTROLTYPE_DATA != buffer[0]) && (0x3 != buffer[0]))   // buffer[0]！=ADPT_COMMCONTROLTYPE_DATA是01 且不等於03
	{
		resCode = DCM_E_REQUESTOUTOFRANGE;  //回復 31
	}
	else
	{
		*respSize = 0x00u;
	}


	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of writting fingerprint.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
/*lint -e{818}*/
bl_ResponseCode_t Adpt_UdsCallBackWriteFingerprint(bl_BufferSize_t size,
												   bl_Buffer_t *buffer,
												   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_GENERALPROGRAMMINGFAILURE;
//    bl_Return_t ret;
	(void)size;
	uint32_t data;
	uint8_t i;
	/*write fingerprint data.*/
	#if (LBM_FUN_SAVE_FINGERPRINT == BL_FUN_ON)
	#ifdef BL_EEPROM_EN
	(void)IntEeprom_WriteBytes(EEPROM_START_ADDRESS, buffer, RTE_FINGERPRINT_SIZE);
	#endif
	for(i = 0; i < APPLICATION_SOFTWARE_FINGERPRINT_EE_FLASH_SIZE; i ++)
	{
		data = buffer[i * 4 + 3];
		data <<= 8;
		data |= buffer[i * 4 + 2];
		data <<= 8;
		data |= buffer[i * 4 + 1];
		data <<= 8;
		data |= buffer[i * 4];
		EE_WriteVariable(APPLICATION_SOFTWARE_FINGERPRINT_BYTE0_3_EE_FLASH_ADDRESS + i, data);
	}
	
	#endif
	Rte_SetDownStatus(&g_DownContext, RTE_SYSFLAG_WRITE_FINGPRINT);
	*respSize = 0u;
	resCode = DCM_E_POSITIVERESPONSE;
	return resCode;
}


bl_ResponseCode_t Adpt_UdsCallBackWriteProgrammingDate(bl_BufferSize_t size,
												   bl_Buffer_t *buffer,
												   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_GENERALPROGRAMMINGFAILURE;
//    bl_Return_t ret;
	(void)size;
	/*write PGM date TO RAM  */
	#if (LBM_FUN_SAVE_PROGRAMMING_DATE == BL_FUN_ON)
	#ifdef BL_EEPROM_EN
	(void)IntEeprom_WriteBytes(EEPROM_START_ADDRESS+0x14, buffer, RTE_PGM_DATE_SIZE);
	//(void)EEPROM_SetWord((EEPROM_TAddress)(EEPROM_DATA_BASE_ADDR+EEPROM_START_ADDRESS+0x14), ((bl_u16_t)(buffer[0]<<8))|buffer[0]);
	//(void)EEPROM_SetWord((EEPROM_TAddress)(EEPROM_DATA_BASE_ADDR+EEPROM_START_ADDRESS+0x16), ((bl_u16_t)(buffer[2]<<8))|buffer[3]);
	#endif
	#endif
	Rte_SetDownStatus(&g_DownContext, RTE_SYSFLAG_WRITE_OTHER);
	*respSize = 0u;
	resCode = DCM_E_POSITIVERESPONSE;
	return resCode;
}


/**************************************************************************//**
 *
 *  \details Callback of checking programming contiditions.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallbackCheckProgramCond(bl_BufferSize_t size,
												   bl_Buffer_t *buffer,
												   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;

	(void)size;

	*respSize = 0x01u;
	buffer[0] = ADPT_ROUTINE_CORRECT_RESULT;

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of erasing memory.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallbackEraseMemory(bl_BufferSize_t size,
											  bl_Buffer_t *buffer,
											  bl_BufferSize_t *respSize)
{
	bl_Size_t eraseSize;
	bl_Address_t address;
	bl_ResponseCode_t resCode = DCM_E_CONDITIONSNOTCORRECT;
	bl_Return_t ret;
        bl_u8_t addrvalid;

        addrvalid = 0;
        if(0 == size)
        {
                address = APP_ADRRESS_VECTOR;//BL_BE32_TO_MCU(&buffer[ADPT_UDS_ERASE_MEMORY_ADDRESS_POS]);
		eraseSize = APP_LENGTH;//BL_BE32_TO_MCU(&buffer[ADPT_UDS_ERASE_MEMORY_SIZE_POS]);
                addrvalid = 1;
        }
        else if((bl_Buffer_t)ADPT_MEMORY_LENANDADDR_FORMAT
		== buffer[ADPT_UDS_ERASE_MEMORY_FORMAT_POS])
	{
		address = BL_BE32_TO_MCU(&buffer[ADPT_UDS_ERASE_MEMORY_ADDRESS_POS]);
		eraseSize = BL_BE32_TO_MCU(&buffer[ADPT_UDS_ERASE_MEMORY_SIZE_POS]);
                
                addrvalid = 1;
        }
        else
        {
                addrvalid = 0;
        }
        if(1 == addrvalid)
        {
		gs_UdsPrivateData.serviceId = ADPT_UDS_31_SERVICE_ID;
		_Adpt_TimeOutCallBack(ADPT_UDS_31_SERVICE_ID);  //負響應78

		ret = Adpt_EraseLB(&g_DownContext, address, eraseSize);
		if(BL_ERR_OK == ret)
		{
			buffer[0] = ADPT_ROUTINE_CORRECT_RESULT;
		}
		else
		{
			Rte_ClearDownStatus(&g_DownContext, ADPT_UDS_STATUS_MASK);
                        buffer[0] = ADPT_ROUTINE_INCORRECT_RESULT; //*buffer = ADPT_ROUTINE_INCORRECT_RESULT;  //
		}
		*respSize = 0x01u;
		resCode = DCM_E_POSITIVERESPONSE;        
        }

	
	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of checksum.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallbackCheckSum(bl_BufferSize_t size,
										   bl_Buffer_t *buffer,
										   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;

	gs_UdsPrivateData.serviceId = ADPT_UDS_31_SERVICE_ID;
	_Adpt_TimeOutCallBack(ADPT_UDS_31_SERVICE_ID);

	ret = Adpt_VerifyData(&g_DownContext, (bl_Size_t)size, buffer);   //这里需要改动，因为接口变了。
	if(BL_ERR_OK == ret)
	{
		buffer[0] = ADPT_ROUTINE_CORRECT_RESULT;  //正确
		buffer[1] = ADPT_ROUTINE_CORRECT_RESULT;  //正确
	}
	else
	{
		buffer[0] = ADPT_ROUTINE_INCORRECT_RESULT;
		buffer[1] = ADPT_ROUTINE_CORRECT_RESULT;  //正确
	}

	Rte_ClearDownStatus(&g_DownContext, ADPT_UDS_STATUS_MASK);

	*respSize = 0x02u;

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of checking compatibility.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallbackCheckCompatibility(bl_BufferSize_t size,
													 bl_Buffer_t *buffer,
													 bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;

	(void)size;

	ret = Adpt_CheckCompatibility();
	if(BL_ERR_OK == ret)
	{
		buffer[0] = ADPT_ROUTINE_CORRECT_RESULT;
	}
	else
	{
		buffer[0] = ADPT_ROUTINE_INCORRECT_RESULT;
	}

	_Adpt_UdsClearDownInfo(&gs_UdsPrivateData);

	*respSize = 0x01u;

	return resCode;
}

#if (RTE_FUN_STAY_IN_BOOT == BL_FUN_ON)
/**************************************************************************//**
 *
 *  \details Callback of stayinboot.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallbackStayInBoot(bl_BufferSize_t size,
											 bl_Buffer_t *buffer,
											 bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;

	(void)buffer;
	(void)size;

	*respSize = 0x00u;

	return resCode;
}
#endif

/**************************************************************************//**
 *
 *  \details Callback of requesting download.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback34(bl_BufferSize_t size,
									 bl_Buffer_t *buffer,
									 bl_BufferSize_t *respSize)
{
	bl_Size_t reqSize;
	bl_Address_t addr;
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;

	(void)size;
	tFlashOptInfo *l_pstFlashOptInfo = (void *)0;
	l_pstFlashOptInfo = (tFlashOptInfo *)flashDriverStartAdd;

	do
	{
		if(g_DownContext.lbId == /*LBM_LB1_ID_APP*/0)
		{
			if( (l_pstFlashOptInfo->magic != FLASH_DRIVER_VERSION_MAGIC ) || (l_pstFlashOptInfo->version != FLASH_DRIVER_VERSION_VERSION) )
			{
				resCode = DCM_E_GENERALREJECT;
				break;
			}
		}

		ret = Rte_IsValidStatus(&g_DownContext, ADPT_STATUS_ALLOW_TRANS_DATA);
		if(BL_ERR_OK == ret)
		{
			resCode = DCM_E_REQUESTSEQUENCEERROR;
			break;
		}

		if((ADPT_DATAFORMAT_IDEN != buffer[ADPT_UDS_34_SERVICE_IDEN_POS])
			|| (ADPT_MEMORY_LENANDADDR_FORMAT
					!= buffer[ADPT_UDS_34_SERVICE_ADDRANDSIZE_POS]))
		{
			resCode = DCM_E_CONDITIONSNOTCORRECT;
			break;
		}

		addr = BL_BE32_TO_MCU(&buffer[ADPT_UDS_34_SERVICE_ADDRESS_POS]);
		reqSize = BL_BE32_TO_MCU(&buffer[ADPT_UDS_34_SERVICE_SIZE_POS]);  /*PRQA S 1840*/

		ret = Adpt_ActivateDownload(&g_DownContext, addr, reqSize);
		if(BL_ERR_OK == ret)
		{
			buffer[ADPT_UDS_34_RESPONSE_FORMAT_POS] = ADPT_LENFORMAT_IDEN;

#if(1u == ADPT_IDEN_LEN_FORMAT)
			/*get maxnum of block length.*/
			buffer[ADPT_UDS_34_RESPONSE_SIZE_POS] = ADPT_MAXNUM_OF_BLOCKLENGTH;
#elif (2u == ADPT_IDEN_LEN_FORMAT)
			BL_MCU_TO_BE16(&buffer[ADPT_UDS_34_RESPONSE_SIZE_POS],
							ADPT_MAXNUM_OF_BLOCKLENGTH);
#else
#error "ADPT_IDEN_LEN_FORMAT is error."
#endif

			gs_UdsPrivateData.address = addr;
			gs_UdsPrivateData.remainSize = reqSize;
			gs_UdsPrivateData.blockIndex = 0x01u;

			*respSize = ADPT_REQDOWNLOAD_RESPLENGTH;

			Rte_SetDownStatus(&g_DownContext, ADPT_STATUS_ALLOW_TRANS_DATA);
		}
		else
		{
			resCode = DCM_E_GENERALREJECT;
		}
	}while(0);/*lint !e717*/

	if (resCode != DCM_E_POSITIVERESPONSE)
	{
		_Adpt_UdsClearDownInfo(&gs_UdsPrivateData);
	}
	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of transferring data.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
/*lint -e{818}*/
bl_ResponseCode_t Adpt_UdsCallback36(bl_BufferSize_t size,
									 bl_Buffer_t *buffer,	//這裡的數據，己經去掉了sid 或者 sudid did等
									 bl_BufferSize_t *respSize)
{
	bl_u8_t expendIndex;
	bl_Size_t dataSize;
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;

	dataSize = (bl_Size_t)((bl_Size_t)size - 1u); /*overflow checking is not required.*/

	do
	{
                /*强制允许下载DATA FLASH*/
               if(g_DownContext.lbId == 2)
               {
                   g_DownContext.status[0] |= 4;
                   //g_DownContext.status[1] |= 4;
               }
               
		ret = Rte_IsValidStatus(&g_DownContext, ADPT_STATUS_ALLOW_TRANS_DATA);
		if (ret != BL_ERR_OK)
		{
			resCode = DCM_E_REQUESTSEQUENCEERROR;
			break;
		}

		expendIndex = gs_UdsPrivateData.blockIndex;

		ret = Rte_IsValidStatus(&g_DownContext,ADPT_STATUS_SEGMENT_FIRST_DATA);
		if(BL_ERR_NOT_OK == ret)
		{
			if (buffer[ADPT_UDS_36_SERVICE_INDEX_POS] != expendIndex)
			{
				resCode = DCM_E_WRONGBLOCKSEQUENCECOUNTER;  //顺序
				break;
			}
			/*set first 0x36 service of a download segment.*/
			Rte_SetDownStatus(&g_DownContext, ADPT_STATUS_SEGMENT_FIRST_DATA);
		}

#if(ADPT_FUN_FIRST_DATA_PREPROCESS == BL_FUN_ON)
		ret = Rte_IsValidStatus(&g_DownContext, ADPT_STATUS_BLOCK_FIRST_DATA);
		if(BL_ERR_NOT_OK == ret)
		{

			/*set first 0x36 service of a logical block.*/
			Rte_SetDownStatus(&g_DownContext, ADPT_STATUS_BLOCK_FIRST_DATA);

			App_PreprocessData();
		}
#endif

		/*check whether the SN is valid.*/
		if(buffer[ADPT_UDS_36_SERVICE_INDEX_POS] != expendIndex)
		{
			if (buffer[ADPT_UDS_36_SERVICE_INDEX_POS] != (expendIndex - 1u))
			{
				resCode = DCM_E_WRONGBLOCKSEQUENCECOUNTER;
			}
			else
			{
				/*repeat request*/
				resCode = DCM_E_POSITIVERESPONSE;
			}
			break;
		}

		/*Check the size of received data.*/
		if(gs_UdsPrivateData.remainSize > ADPT_MAXNUM_OF_TRANS_DATA)
		{
			/*It is not the last 0x36 service.*/
			if(ADPT_MAXNUM_OF_TRANS_DATA != dataSize)
			{
				resCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
				break;
			}
		}
		else if(gs_UdsPrivateData.remainSize != dataSize)
		{
			resCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
			break;
		}
		else
		{
			/*last service and data size is ok.*/
		}

		/*send 0x78.*/
		gs_UdsPrivateData.serviceId = ADPT_UDS_36_SERVICE_ID;
		_Adpt_TimeOutCallBack(ADPT_UDS_36_SERVICE_ID);
		#ifdef UDS_DEBUG_EN
		g_usd_test.data[0]++;
		#endif
		ret = Adpt_DownloadData(&g_DownContext,
									gs_UdsPrivateData.address,
									dataSize,
									&buffer[ADPT_UDS_36_SERVICE_DATA_POS]);
		if(BL_ERR_OK != ret)
		{
			resCode = DCM_E_GENERALPROGRAMMINGFAILURE;
			break;
		}
		else
		{
			*respSize = 0x01u;
			gs_UdsPrivateData.blockIndex++;
			gs_UdsPrivateData.address += dataSize;
			gs_UdsPrivateData.remainSize -= dataSize;
		}
	}while(0);/*lint !e717*/

	if (resCode != DCM_E_POSITIVERESPONSE)
	{
		_Adpt_UdsClearDownInfo(&gs_UdsPrivateData);
	}

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of requesting transfer exit.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback37(bl_BufferSize_t size,
									 bl_Buffer_t *buffer,
									 bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;
	bl_Return_t ret;

	(void)buffer;
	(void)size;

	ret = Rte_IsValidStatus(&g_DownContext,
								ADPT_STATUS_ALLOW_TRANS_DATA);
	if(BL_ERR_OK != ret)
	{
		_Adpt_UdsClearDownInfo(&gs_UdsPrivateData);

		resCode = DCM_E_REQUESTSEQUENCEERROR;
	}
	else
	{
		Rte_ClearDownStatus(&g_DownContext,
								(ADPT_STATUS_SEGMENT_FIRST_DATA
								| ADPT_STATUS_ALLOW_TRANS_DATA));
		*respSize = 0x00u;
	}
	#ifdef UDS_DEBUG_EN
	g_usd_test.data[1]++;
	#endif
	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of keeping session.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval 0x00   - Positive response code.
 *  \retval others - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback3E(bl_BufferSize_t size,
									 bl_Buffer_t *buffer,
									 bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;

	(void)size;
	(void)buffer;

#if(RTE_FUN_GATEWAY == BL_FUN_ON)
		_Adpt_UdsGatewayTransmit(ADPT_UDS_3E_SERVICE_ID);
#endif

	*respSize = 0x00u;

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Callback of switching on of off dtc.
 *
 *  \param[in]     size     - the data size, not include id, subid and did.
 *  \param[in/out] buffer   - the pointer of data.
 *  \param[out]    respSize - the size of response data.
 *
 *  \return Return response code.
 *
 *  \retval DCM_E_POSITIVERESPONSE   - Positive response code.
 *  \retval DCM_E_SUBFUNCTIONNOTSUPPORTED - Negative response code.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
bl_ResponseCode_t Adpt_UdsCallback85(bl_BufferSize_t size,
									   bl_Buffer_t *buffer,
									   bl_BufferSize_t *respSize)
{
	bl_ResponseCode_t resCode = DCM_E_POSITIVERESPONSE;

	(void)size;
	(void)buffer;

	*respSize = 0x00u;

	return resCode;
}

/**************************************************************************//**
 *
 *  \details Timeout callback of sending 0x78.
 *
 *  \param[in]  id  - service id.
 *
 *  \since  V3.0.0
 *  是靠 Rte_ReportEvent(RTE_EVENT_TYPE_MEMOPS_TIMEOUT);  //要發送 78負響應 調用 的
 *****************************************************************************/
void Adpt_UdsTimeOutCallBack(void)
{
	#ifdef UDS_DEBUG_EN
	g_usd_test.time[4]++;
	if(g_usd_test.time[4]>=1000)
	{
		g_usd_test.time[4]=0;
		g_usd_test.time[5]++;
	}
	#endif
	_Adpt_TimeOutCallBack(gs_UdsPrivateData.serviceId);

	return ;
}

//
void Adpt_Res_default_ValidProcess(void)
{
	bl_u8_t i;
	bl_u8_t l_buf[ADPT_UDS_MAX_CAN_FRAME_SIZE];
	Dcm_StartS3Timer();

	Rte_SetMutexDownStatus(&g_DownContext,
							DCM_STATUS_SESSION_DEFAULT,
							DCM_SESSION_MASK);

	for(i=0;i<8;i++)
	{
		l_buf[i] = gs_DefaultResponse[i];
	}
	for(i=8;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
	{
		l_buf[i] = CANTP_FRAME_PADDING_VALUE;
	}
	_Adpt_SendResponse((bl_BufferSize_t)sizeof(l_buf),l_buf);

	return ;
}

/**************************************************************************//**
 *
 *  \details When the reprogram flag is valid, the RTE module call this
 *           function.
 *
 *  \since  V3.0.0
 *  好像只被用到一次；如果從app 跳轉到 boot 則要響應 0x06u,0x50u,0x02u,
 *****************************************************************************/
void Adpt_ReprogramValidProcess(void)
{
	bl_u8_t i;
	bl_u8_t l_buf[ADPT_UDS_MAX_CAN_FRAME_SIZE];
	Dcm_StartS3Timer();

	Rte_SetMutexDownStatus(&g_DownContext,
							DCM_STATUS_SESSION_PROGRAMMING,
							DCM_SESSION_MASK);

	for(i=0;i<8;i++)
	{
		l_buf[i] = gs_ReprogrammingResponse[i];
	}
	for(i=8;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
	{
		l_buf[i] = CANTP_FRAME_PADDING_VALUE;
	}
	_Adpt_SendResponse((bl_BufferSize_t)sizeof(l_buf),l_buf);

	return ;
}

/**************************************************************************//**
 *
 *  \details When the reprogram flag is valid, the RTE module call this
 *           function.
 *
 *  \since  V3.0.0
 *  好像只被用到一次；如果從app 跳轉到 boot 則要響應 0x06u,0x50u,0x02u,
 *****************************************************************************/
void Adpt_ReprogramValid_nores_Process(void)
{
	#ifdef SERVICE_36_BLOCK_REPEATE
	g_36_block_repeat_count=0;
	#endif

	Dcm_StartS3Timer();

	Rte_SetMutexDownStatus(&g_DownContext,
							DCM_STATUS_SESSION_PROGRAMMING,
							DCM_SESSION_MASK);
	#if 0
	_Adpt_SendResponse((bl_BufferSize_t)sizeof(gs_ReprogrammingResponse),
						gs_ReprogrammingResponse);
	#endif
	return ;
}
/**************************************************************************//**
 *
 *  \details When the reset flag is valid, the RTE module call this function.
 *
 *  \since  V3.0.0
 *  0x02u,0x51u,0x01u  好像目前沒有用到
 *****************************************************************************/
void Adpt_SystemResetProcess(void)
{
	u8 i;
	u8 l_buf[ADPT_UDS_MAX_CAN_FRAME_SIZE];
	for(i=0;i<8;i++)
	{
		l_buf[i] = gs_ResetResponse[i];
	}
	for(i=8;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
	{
		l_buf[i] = CANTP_FRAME_PADDING_VALUE;
	}
	_Adpt_SendResponse((bl_BufferSize_t)sizeof(gs_ResetResponse),gs_ResetResponse);

	return ;
}

#if (RTE_FUN_STAY_IN_BOOT == BL_FUN_ON)
/**************************************************************************//**
 *
 *  \details When the application is valid and the stay in boot is enabled,
 *           the RTE module call this function.
 *
 *  \since  V3.0.0
 *  0x04u,0x71u,0x01u F5 18
 *****************************************************************************/
void Adpt_AppValidProcess(void)
{
	bl_u8_t i;
	bl_u8_t l_buf[ADPT_UDS_MAX_CAN_FRAME_SIZE];
	for(i=0;i<8;i++)
	{
		l_buf[i] = gs_StayInBootResponse[i];
	}
	for(i=8;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
	{
		l_buf[i] = CANTP_FRAME_PADDING_VALUE;
	}
	_Adpt_SendResponse((bl_BufferSize_t)sizeof(l_buf),l_buf);

	return ;
}
#endif

#if(RTE_FUN_GATEWAY == BL_FUN_ON)
/**************************************************************************//**
 *
 *  \details Gateway transmits messages by id.
 *
 *  \param[in]  id  - service id.
 *
 *  \since  V5.0.0
 *
 *****************************************************************************/
static void _Adpt_UdsGatewayTransmit(bl_u8_t id)
{
	bl_u8_t i;
	bl_u16_t handle;
	bl_u16_t number;
	const bl_GatewayConversion_t *gateway;

	number = gs_UdsGatewayList.number;
	gateway = gs_UdsGatewayList.data;
	handle = gs_UdsGatewayList.handle;

	for(i = 0u; i < number; i++)
	{
		if(id == gateway[i].sid)
		{
			(void)Canif_Write(handle, gateway[i].size, gateway[i].data);
			break;
		}
	}

	return ;
}
#endif

/**************************************************************************//**
 *
 *  \details Send 0x78 negative response.
 *
 *  \param[in]  id  - service id.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
static void _Adpt_UdsPendingResponse(bl_u8_t id)
{
	u8 i;
	#if ADPT_UDS_MAX_CAN_FRAME_SIZE <=8

		bl_Buffer_t buffer[ADPT_UDS_MAX_CAN_FRAME_SIZE];

		buffer[ADPT_UDS_CAN_FRAME_INDEX_0] = DCM_NEGATIVE_RESPONSE_SIZE;
		buffer[ADPT_UDS_CAN_FRAME_INDEX_1] = DCM_NEGATIVE_RESPONSE_CODE;
		buffer[ADPT_UDS_CAN_FRAME_INDEX_2] = id;
		buffer[ADPT_UDS_CAN_FRAME_INDEX_3] =
									DCM_E_REQUESTCORRECTLYRECEIVED_RESPONSEPENDING;
		#if(CANTP_FUN_FRAME_PADDING == BL_FUN_ON)
			for(i=ADPT_UDS_CAN_FRAME_INDEX_4;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
			{
				buffer[i] = CANTP_FRAME_PADDING_VALUE;
			}
		#endif
	#else

		bl_Buffer_t buffer[ADPT_UDS_MAX_CAN_FRAME_SIZE];

		buffer[ADPT_UDS_CAN_FRAME_INDEX_0] = 0x00;
		buffer[ADPT_UDS_CAN_FRAME_INDEX_1] = DCM_NEGATIVE_RESPONSE_SIZE;
		buffer[ADPT_UDS_CAN_FRAME_INDEX_2] = DCM_NEGATIVE_RESPONSE_CODE;
		buffer[ADPT_UDS_CAN_FRAME_INDEX_3] = id;
		buffer[ADPT_UDS_CAN_FRAME_INDEX_4] =
									DCM_E_REQUESTCORRECTLYRECEIVED_RESPONSEPENDING;
		#if(CANTP_FUN_FRAME_PADDING == BL_FUN_ON)
			for(i=ADPT_UDS_CAN_FRAME_INDEX_5;i<ADPT_UDS_MAX_CAN_FRAME_SIZE;i++)
			{
				buffer[i] = CANTP_FRAME_PADDING_VALUE;
			}
		#endif

	#endif

	_Adpt_SendResponse((bl_BufferSize_t)sizeof(buffer), buffer);

	return ;
}

/**************************************************************************//**
 *
 *  \details Send a response by ComOps in the g_RteInfo. When the transmitter
 *           is activated, This function will wait for some time configurated
 *           by ADPT_UDS_TX_TIMEOUT. If the response is not send within this
 *           time, this function will still return.
 *
 *  \param[in]  size    - the size of buffer.
 *  \param[in]  buffer  - the data will be send.
 *
 *  \since  V3.0.0
 *
 *****************************************************************************/
static void _Adpt_SendResponse(bl_BufferSize_t size, const bl_Buffer_t *buffer)
{
	#if ADPT_UDS_MAX_CAN_FRAME_SIZE <=8
	bl_u32_t timeout = ADPT_UDS_TX_TIMEOUT;
	#else
	bl_u32_t timeout = ADPT_UDS_CANFD_TX_TIMEOUT;
	#endif

	/*whether return value is necessary*/
	(void)Canif_Write(ADPT_UDS_TX_HANDLE, size, buffer);

	BL_WAITFOR_TIMEOUT(timeout,
						Canif_IsWritten(ADPT_UDS_TX_HANDLE) == BL_ERR_OK)

	return ;
}
/**************************************************************************//**
 *
 *  \details Timeout callback of sending 0x78.
 *
 *  \param[in]  id  - service id.
 *
 *  \since  V2.0.0
 *  負響應  78
 *****************************************************************************/
static void _Adpt_TimeOutCallBack(bl_u8_t id)
{
	_Adpt_UdsPendingResponse(id);

#if(RTE_FUN_GATEWAY == BL_FUN_ON)
	_Adpt_UdsGatewayTransmit(ADPT_UDS_3E_SERVICE_ID);
#endif
}

/**************************************************************************//**
 *
 *  \details Set response info of session.
 *
 *  \param[out]  buffer  - the pointer of response data.
 *
 *  \return Return the size of response data.
 *
 *  \since  V4.0.0
 *  會話的應答時間參數
 *****************************************************************************/
static bl_BufferSize_t _Adpt_SetSessionResp(bl_Buffer_t *buffer)
{
	bl_BufferSize_t size;

	size = ADPT_SESSION_RESPONSE_LEN;

	buffer[ADPT_UDS_CAN_FRAME_INDEX_0] = ADPT_SESSION_RESPONSE0;
	buffer[ADPT_UDS_CAN_FRAME_INDEX_1] = ADPT_SESSION_RESPONSE1;
	buffer[ADPT_UDS_CAN_FRAME_INDEX_2] = ADPT_SESSION_RESPONSE2;
	buffer[ADPT_UDS_CAN_FRAME_INDEX_3] = ADPT_SESSION_RESPONSE3;

	return size;
}

/**************************************************************************//**
 *
 *  \details Go to the session
 *
 *  \param[in] sessionMask - the session will be gone.
 *
 *  \since  V5.0.0
 *
 *****************************************************************************/
static void _Adpt_UdsGotoSession(bl_DownStatus_t sessionMask)
{
	_Adpt_UdsClearDownInfo(&gs_UdsPrivateData);  /*
													adpt->address = 0;
													adpt->remainSize = 0;
													adpt->blockIndex = 0;
													再清 g_DownContext.state[0-1]
													state[0]一般指#define RTE_SYSFLAG_SECURITY_ACCESS     (0x00000001UL)
														#define RTE_SYSFLAG_CHECK_SIGNATURE     (0x00000002UL)
														#define RTE_SYSFLAG_ERASE_BLOCK         (0x00000004UL)
														#define RTE_SYSFLAG_WRITE_DATA          (0x00000008UL)
														#define RTE_SYSFLAG_WRITE_FINGPRINT     (0x00000010UL)  //寫入金手指，具體是什麼？
														#define RTE_SYSFLAG_WRITE_OTHER         (0x00000020UL)
													state[1]一般指 RTE_USER_FLAG_GROUP_1
														下面包含 ALLOW_TRANS_DATA ；BLOCK_FIRST_DATA ； SEGMENT_FIRST_DATA ; SEGMENT_FIRST_DATA
														所有 DCM診斷相關
													*/

#if (DCM_FUN_SECURITY_ACCESS == BL_FUN_ON)
	/*lock the level 1.*/
	Rte_SetMutexDownStatus(&g_DownContext,
							DCM_STATUS_SECURITY_LOCK_1,  //40000100
							DCM_SECURITYACCESS_1_MASK);  //40000700  相當於清除其余兩個 再置 DCM_STATUS_SECURITY_LOCK_1
#else
	/*unlock the level 1.*/
	Rte_SetMutexDownStatus(&g_DownContext,
							DCM_STATUS_SECURITY_UNLOCK_1,  //40000200
							DCM_SECURITYACCESS_1_MASK);  //40000700  相當於清除其余兩個 再置 DCM_SECURITYACCESS_1_MASK
#endif
	Rte_SetMutexDownStatus(&g_DownContext,
							sessionMask,    //
							DCM_SESSION_MASK);   //40000007 相當於清除其余兩個  再置sessionMask

	return ;
}

/**************************************************************************//**
 *
 *  \details Clear the download information.
 *
 *  \since  V5.1.0
 *
 *****************************************************************************/
static void _Adpt_UdsClearDownInfo(bl_AdapterData_t *adpt)
{
	adpt->address = 0;
	adpt->remainSize = 0;
	adpt->blockIndex = 0;

	Rte_ClearDownStatus(&g_DownContext, ADPT_UDS_SYSTEM_STATUS_MASK);  //1c  state[0]
																		/*
																		 (RTE_SYSFLAG_ERASE_BLOCK \  4
																			| RTE_SYSFLAG_WRITE_DATA)  //8
																			| RTE_SYSFLAG_WRITE_FINGPRINT 10
																		 */
	Rte_ClearDownStatus(&g_DownContext, ADPT_UDS_STATUS_MASK);  //78000000  state[1]
																/*
																	(ADPT_STATUS_ALLOW_TRANS_DATA \
																	| ADPT_STATUS_BLOCK_FIRST_DATA \
																	| ADPT_STATUS_SEGMENT_FIRST_DATA)  //78000000
																 */
	return ;
}

/**************************************************************************//**
 *
 *  \details Reset the system.
 *
 *  \since  V5.1.0
 *  好像沒有用到
 *****************************************************************************/
static void _Adpt_UdsResetSystem(bl_u8_t sid, bl_u16_t flagId)
{
	bl_Return_t ret;

	ret = Dcm_IsSuspendedResponse(); //gs_SupPosRespFlag==0
	if (ret != BL_ERR_OK)
	{
		_Adpt_TimeOutCallBack(sid);
		/*write flag.*/
		(void)Dm_WriteDefaultData(flagId);
	}

	g_RteInfo.SystemReset();
}








void  adpt_test_init(void)
{
	(void)Dm_WriteDefaultData(BOOTM_REPROGRAM_FLAG_DID);
}
